<?php


namespace coco;


use coco\traits\Singleton;

class Request
{
    use Singleton;

    private $param;
    private $body;
    private $header;
    private $cookie;
    private $raw;
    private $controller;
    private $real_controller;
    private $method;
    private $real_method;
    private $request_method;

    private function __construct()
    {
        $this->param = $_GET;
        unset($this->param['s']);
        $this->cookie = $_COOKIE;
        $this->raw = file_get_contents("php://input");
        $header = [];
        foreach ($_SERVER as $k => $v) {
            if (substr($k, 0, 5) === 'HTTP_') {
                $header[str_replace('_', '-', strtolower(substr($k, 5)))] = $v;
            }
        }
        $this->request_method = strtolower($_SERVER['REQUEST_METHOD']);
        $this->header = $header;
        $content_type = $header['content-type'] ?? 'application/x-www-form-urlencoded;charset=utf-8';
        $type = explode(';', $content_type)[0];
        $sub_type = explode('/', $type)[1];
        switch ($sub_type) {
            case 'json':
                $this->body = json_decode($this->raw, true);
                break;
            case 'x-www-form-urlencoded':
                parse_str($this->raw, $this->body);
                break;
            case 'form-data':
            default:
                $this->body = $_POST;
        }
        $url = !empty($_GET['s']) ? $_GET['s'] : '/index/index';
        if (false === strpos($url, '/')) {
            $controller = 'Index';
            $method = 'index';
        } else {
            $path_array = explode('/', $url);
            $method = lcfirst(url2class(array_pop($path_array)));
            $len = count($path_array);
            //最后个下划线转换驼峰
            $path_array[$len - 1] = url2class($path_array[$len - 1]);
            $controller = '\\app\\controller' . join('\\', $path_array);
        }

        $this->real_controller = $controller;
        $this->real_method = $method;
        //请求兜底
        if (!class_exists($controller)) {
            $empty_controller = '\\app\\controller\\EmptyController';
            if (class_exists($empty_controller)) {
                $controller = $empty_controller;
                $method = '_empty';
            }
        }

        $this->controller = $controller;
        $this->method = $method;
    }


    /**
     * @return string
     */
    public function getController(): string
    {
        return $this->controller;
    }

    /**
     * @return string
     */
    public function getRealController(): string
    {
        return $this->real_controller;
    }

    /**
     * @return string
     */
    public function getMethod(): string
    {
        return $this->method;
    }

    /**
     * @return string
     */
    public function getRealMethod(): string
    {
        return $this->real_method;
    }

    /**
     * @return array
     */
    public function getHeader(): array
    {
        return $this->header;
    }

    /**
     * @return false|string
     */
    public function getRaw()
    {
        return $this->raw;
    }

    /**
     * @return array|mixed
     */
    public function getBody(): array
    {
        return $this->body;
    }

    public function post(string $name = '')
    {
        $data = $this->body;
        if (empty($name)) {
            return $data;
        }
        if (false !== strpos($name, ',')) {
            $names = explode(',', $name);
            $return = [];
            foreach ($names as $name) {
                $return[$name] = self::filter($name, $data);
            }
            return $return;
        }
        return self::filter($name, $data);
    }

    public function get(string $name = '')
    {
        $data = $this->param;
        if (empty($name)) {
            return $data;
        }
        if (false !== strpos($name, ',')) {
            $names = explode(',', $name);
            $return = [];
            foreach ($names as $name) {
                $return[$name] = self::filter($name, $data);
            }
            return $return;
        }
        return self::filter($name, $data);
    }

    protected static function filter(&$name, $data)
    {
        if ('/d' === substr($name, -2)) {
            $name = substr($name, 0, -2);
            $return = !empty($data[$name]) ? $data[$name] : '';
            $return = (int)$return;
        } elseif ('/f' === substr($name, -2)) {
            $name = substr($name, 0, -2);
            $return = !empty($data[$name]) ? $data[$name] : '';
            $return = (float)$return;
        } elseif ('/s' === substr($name, -2)) {
            $name = substr($name, 0, -2);
            $return = !empty($data[$name]) ? $data[$name] : '';
            $return = (string)$return;
        } elseif ('/a' === substr($name, -2)) {
            $name = substr($name, 0, -2);
            $return = !empty($data[$name]) ? $data[$name] : [];
            $return = (array)$return;
        } else {
            $return = !empty($data[$name]) ? $data[$name] : '';
        }
        return $return;
    }

    /**
     * @return array
     */
    public function getParam(): array
    {
        return $this->param;
    }

    /**
     * @return array
     */
    public function getCookie(): array
    {
        return $this->cookie;
    }

    /**
     * @return mixed
     */
    public function getRequestMethod(): string
    {
        return $this->request_method;
    }

    public function is_post(): bool
    {
        return $this->request_method === 'post';
    }

    public function is_get(): bool
    {
        return $this->request_method === 'get';
    }
}